package com.ruicar.afs.cloud.account.common.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.account.common.entity.VoucherAtom;
import com.ruicar.afs.cloud.account.common.entity.VoucherAtomBusinessRel;
import com.ruicar.afs.cloud.account.common.entity.VoucherAtomOperatorRel;
import com.ruicar.afs.cloud.account.common.entity.VoucherRuleInputMapping;
import com.ruicar.afs.cloud.account.common.mapper.VoucherAtomMapper;
import com.ruicar.afs.cloud.account.common.service.VoucherAtomBusinessRelService;
import com.ruicar.afs.cloud.account.common.service.VoucherAtomOperatorRelService;
import com.ruicar.afs.cloud.account.common.service.VoucherAtomService;
import com.ruicar.afs.cloud.account.common.service.VoucherRuleInputMappingService;
import com.ruicar.afs.cloud.account.common.util.SqlFormatUtil;
import com.ruicar.afs.cloud.account.dto.atom.VoucherAtomDto;
import com.ruicar.afs.cloud.account.vo.VoucherAtomVo;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.query.QueryCondition;
import com.ruicar.afs.cloud.common.core.uid.UidGenerator;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.modules.contract.enums.AtomComponentType;
import com.ruicar.afs.cloud.common.voucher.handle.VoucherCaches;
import lombok.AllArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author infinity
 * @version 1.0
 * @date 2020/6/23 20:34
 */
@Service
@AllArgsConstructor
public class VoucherAtomServiceImpl extends ServiceImpl<VoucherAtomMapper, VoucherAtom> implements VoucherAtomService {
    private final VoucherAtomBusinessRelService voucherAtomBusinessRelService;
    private final VoucherAtomOperatorRelService voucherAtomOperatorRelService;
    private final VoucherRuleInputMappingService voucherRuleInputMappingService;
    private final UidGenerator uidGenerator;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addVoucherAtom(VoucherAtomVo voucherAtomVo) {
        check(voucherAtomVo);
        VoucherAtom voucherAtom = VoucherAtom.convertFromVo(voucherAtomVo);
        voucherAtom.setAtomKey(getAtomKey());
        this.baseMapper.insert(voucherAtom);
        insetRelInfo(voucherAtomVo, voucherAtom);
        return Boolean.TRUE;
    }

    private void check(VoucherAtomVo voucherAtomVo) {
        if(AtomComponentType.TEXT.equals(voucherAtomVo.getAtomType())) {
            //校验sql语句
            SqlFormatUtil.sqlFormat(voucherAtomVo.getAtomValueExpress());
        }else{
         //判断字符串是否为金额
            Pattern pattern= Pattern.compile("^(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){0,4})?$"); // 判断小数点后4位的数字的正则表达式
            Matcher match=pattern.matcher(voucherAtomVo.getAtomValueExpress().trim());
            Assert.isTrue(match.matches(),"原子key[" + voucherAtomVo.getAtomKey() + "]值不是数字类型，最多保留四位小数");
            }
        long count = this.baseMapper.selectCount(Wrappers.<VoucherAtom>lambdaQuery()
                .eq(VoucherAtom::getAtomKey, voucherAtomVo.getAtomKey()).ne(voucherAtomVo.getId() != null, VoucherAtom::getId, voucherAtomVo.getId()));
        Assert.isTrue(count < 1, "原子key[" + voucherAtomVo.getAtomKey() + "]重复");
    }

    private void insetRelInfo(VoucherAtomVo voucherAtomVo, VoucherAtom voucherAtom) {
        if (voucherAtomVo.getRelList() != null) {
            voucherAtomVo.getRelList().forEach(dicValue -> {
                VoucherAtomBusinessRel voucherAtomBusinessRel = new VoucherAtomBusinessRel();
                voucherAtomBusinessRel.setAtomId(voucherAtom.getId());
                voucherAtomBusinessRel.setBusinessDicValue(dicValue);
                voucherAtomBusinessRelService.save(voucherAtomBusinessRel);
            });
        }
        if (voucherAtomVo.getOperatorKeyList() != null) {
            voucherAtomVo.getOperatorKeyList().forEach(operatorKey -> {
                VoucherAtomOperatorRel voucherAtomOperatorRel = new VoucherAtomOperatorRel();
                voucherAtomOperatorRel.setAtomId(voucherAtom.getId());
                voucherAtomOperatorRel.setOperatorKey(operatorKey);
                voucherAtomOperatorRelService.save(voucherAtomOperatorRel);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean delVoucherAtom(String id) {
        VoucherAtom atom = this.getById(id);
        Assert.isTrue(atom != null, "删除失败，凭证原子不存在!");
        long count = voucherRuleInputMappingService.count(Wrappers.<VoucherRuleInputMapping>lambdaQuery()
                .eq(VoucherRuleInputMapping::getAtomKey, atom.getAtomKey()));
        Assert.isTrue(count <= 0, "原子key[" + atom.getAtomKey() + "]已被使用不可删除！");
        voucherRuleInputMappingService.remove(Wrappers.<VoucherRuleInputMapping>lambdaQuery().eq(VoucherRuleInputMapping::getRuleId, id));
        this.update(Wrappers.<VoucherAtom>lambdaUpdate().eq(VoucherAtom::getId, id)
                .set(VoucherAtom::getDeleteToken, uidGenerator.getUID())
                //逻辑删除 1 为删除
                .set(VoucherAtom::getDelFlag, '1'));
        voucherAtomBusinessRelService.remove(Wrappers.<VoucherAtomBusinessRel>lambdaQuery().eq(VoucherAtomBusinessRel::getAtomId, id));
        voucherAtomOperatorRelService.remove(Wrappers.<VoucherAtomOperatorRel>lambdaQuery().eq(VoucherAtomOperatorRel::getAtomId, id));
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean modifyVoucherAtom(VoucherAtomVo voucherAtomVo) {
        VoucherAtom dbVoucherAtom = this.baseMapper.selectById(Long.valueOf(voucherAtomVo.getId()));
        long count = voucherRuleInputMappingService.count(Wrappers.<VoucherRuleInputMapping>lambdaQuery()
                .eq(VoucherRuleInputMapping::getAtomKey, dbVoucherAtom.getAtomKey()));
        if (!dbVoucherAtom.getAtomKey().equals(voucherAtomVo.getAtomKey())) {
            Assert.isTrue(count <= 0, "原子key:[" + dbVoucherAtom.getAtomKey() + "]已被使用不可修改原子key！");
        }
        check(voucherAtomVo);
        if(!voucherAtomVo.getAtomValueExpress().equals(dbVoucherAtom.getAtomValueExpress())&&count>0) {
            Boolean flag = voucherRuleInputMappingService.update(Wrappers.<VoucherRuleInputMapping>update().lambda().set(VoucherRuleInputMapping::getValueExpress, voucherAtomVo.getAtomValueExpress())
                    .set(VoucherRuleInputMapping::getAtomType,voucherAtomVo.getAtomType())
                    .eq(VoucherRuleInputMapping::getAtomKey, voucherAtomVo.getAtomKey()));
            Assert.isTrue(flag, "原子key:[" + voucherAtomVo.getAtomKey() + "]修改原子取值表达式失败！");
            VoucherCaches.resetCache();
        }
        //原子取值表达式修改，凭证重新发布
        VoucherAtom voucherAtom = VoucherAtom.convertFromVo(voucherAtomVo);
        BeanUtil.copyProperties(voucherAtom, dbVoucherAtom, "createBy", "createTime", "id");
        this.baseMapper.updateById(dbVoucherAtom);
        voucherAtomBusinessRelService.remove(Wrappers.<VoucherAtomBusinessRel>lambdaQuery().eq(VoucherAtomBusinessRel::getAtomId, dbVoucherAtom.getId()));
        voucherAtomOperatorRelService.remove(Wrappers.<VoucherAtomOperatorRel>lambdaQuery().eq(VoucherAtomOperatorRel::getAtomId, dbVoucherAtom.getId()));
        insetRelInfo(voucherAtomVo, dbVoucherAtom);
        return Boolean.TRUE;
    }

    @Override
    public IResponse query(QueryCondition<VoucherAtomVo> queryCondition) {
        //查询条件去空格
        queryCondition.getCondition().setAtomKey(queryCondition.getCondition().getAtomKey()!=null?queryCondition.getCondition().getAtomKey().trim():queryCondition.getCondition().getAtomKey());
        queryCondition.getCondition().setAtomName(queryCondition.getCondition().getAtomName()!=null?queryCondition.getCondition().getAtomName().trim():queryCondition.getCondition().getAtomName());
        return IResponse.success(this.baseMapper.queryAtoms(new Page(queryCondition.getPageNumber(), queryCondition.getPageSize()), queryCondition.getCondition()));
    }

    @Override
    public IResponse<List<VoucherAtomDto>> queryAtomsByBizType(String bizType) {
        return IResponse.success(this.baseMapper.queryAtomsByBizType(bizType)
                .stream().map(voucherAtomVo -> {
                    VoucherAtomDto voucherAtomDto = new VoucherAtomDto();
                    voucherAtomDto.setKey(voucherAtomVo.getAtomKey());
                    voucherAtomDto.setName(voucherAtomVo.getAtomName());
                    voucherAtomDto.setValueExpress(voucherAtomVo.getAtomValueExpress());
                    voucherAtomDto.setOperatorScope(AfsEnumUtil.key(voucherAtomVo.getAtomOperatorScope()));
                    voucherAtomDto.setOperatorTypes(voucherAtomVo.getOperatorKeyList());
                    voucherAtomDto.setComponent(AfsEnumUtil.key(voucherAtomVo.getAtomType()));
                    return voucherAtomDto;
                }).collect(Collectors.toList()));
    }
    //获取原子KEY
    public String getAtomKey(){
        VoucherAtom atom =this.getOne(Wrappers.<VoucherAtom>lambdaQuery().orderByDesc(VoucherAtom::getAtomKey),false);
        if(atom==null){
        return "K0001";
        }
        Integer seqNo= Integer.valueOf(atom.getAtomKey().replace("K",""))+1;
        String seqStr = StringUtils.leftPad(seqNo.toString(),4,"0");
        return  "K" + seqStr;
    }
}
